package com.amado.course53EncodeDecode;

import javax.annotation.PostConstruct;
import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * @author xingliang
 * @apiDefine RSA 加密算法
 * @apiExample 加密协议如下：
 * 客户端对需要加密的串str使用URLSAFE_BASE64(RSA(str))协议编码
 * 其中RSA算法为：RSA/ECB/PKCS1Padding
 * 测试公钥为：MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCajLOdwFMIBQ8k3W48/e4bIj2EFc3O/T54oiLOk+KQgAknvmUHJp/1arN8g9tjAaBKPSbznTe4ZYX3VXI7VTRF7Dhi1+vCkas1OwWkdwzZWg3LOqfUORF3tFmvNOiLLzJQ6H5oLsNNZjMOr2QZrm4srzc1aX3O0BRwQhPkP/XhYwIDAQAB
 * 测试私钥为：MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJqMs53AUwgFDyTdbjz97hsiPYQVzc79PniiIs6T4pCACSe+ZQcmn/Vqs3yD22MBoEo9JvOdN7hlhfdVcjtVNEXsOGLX68KRqzU7BaR3DNlaDcs6p9Q5EXe0Wa806IsvMlDofmguw01mMw6vZBmubiyvNzVpfc7QFHBCE+Q/9eFjAgMBAAECgYBu5tBtPvlWI+s+FPdqJP2b0vI5uju5cNhHUHGRs2U9M+Nd9a4hd4IJZcvuaeAgJ6aSH1e4MPUvCQsc9N/H29hpxD+7wWVwnTpIIVy4rgSzkDheGZodQjqtoJTQXzqewEhb+drqtCvJTVEr28k/2q8gMXkNk9Rctlwf/D2NjE5qoQJBAOVQPNtJT0fY1fROsVURFmcM/77viz8LiN7+wl3yvFXwXt92DqSAAk034KH0pai7KGVM+Fgqvt2TjUrzUotNur8CQQCsiRT5mfgeXckOundPM3kmt6R5kCO4EbxBfqE3qki5pW4+0jGyukgbxs5vvXjr/Ut8wEji5CQpJv1aj9kBm3ZdAkBSE2sEzfN7csf5nqToHqqXDdcH3zNGyHkf361v9O6mD9fVQasyA8NPIh3bufYFM5/cyjTlUb9pDWP4HKlBxPt/AkBiuASSVDCNX2f8z2AYpwD40DaBf6GQXkVyy/t+mCYIYslTlHzvIHrFudjAQo7/p+wbMwIBIDw4d6CawpeNvd/ZAkEA29WTAl94zp0X3U6JWyqtn8Ci9jibhhbB0/vpA5igKK1zXg6ir7vk6Tp/hsi48tgYrFd6rciWt4jwpeFv7HDhTA==
 * URLSAFE_BASE64算法在RFC4648中有定义
 * 最终串会使用RSA公钥进行加密，之后使用RFC4648算法编码放入请求体或表单项中。
 */
public class RSAServicePkCs1 {
    /**
     * encrypt str->URLSAFE_BASE64(RSA(str))
     *
     * @param str
     * @return if no exception return URLSAFE_BASE64(RSA(str)) ,
     * else return null
     */
    public static String encrypt(String key, String str) {
        try {
            X509EncodedKeySpec encodeKey = new X509EncodedKeySpec(
                    Base64.getDecoder().decode(key.getBytes()));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = keyFactory.generatePublic(encodeKey);
            Cipher encoder = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            encoder.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] rsa = encoder.doFinal(str.getBytes());
            String base64 = Base64.getUrlEncoder().encodeToString(rsa);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e);
        }
        return null;
    }

    /**
     * decrypt URLSAFE_BASE64(RSA(password))->password
     *
     * @param str URLSAFE_BASE64(RSA(password))
     * @return if no exception return password, else return str.
     */
    public static String decrypt(String key,String str) {
        try {
            PKCS8EncodedKeySpec encodeKey = new PKCS8EncodedKeySpec(
                    Base64.getDecoder().decode(key.getBytes()));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(encodeKey);
            Cipher decoder = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            decoder.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] decodedStr = Base64.getUrlDecoder().decode(str);
            String result = new String(decoder.doFinal(decodedStr));
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e);
        }
        return null;
    }

    public static void main(String[] args) {
        String privateKey = "MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEApvBfJSNjZYdBM8Ut\n" +
                "G7PZLy+YYq7aKHuZKojJhzZnZBXehOOHymI14P7XoiZWgZ9XYe7KP4H4hzpiyqS2\n" +
                "0kkjawIDAQABAkEAltPeYuOSTozhcDDaDIl11JggCikImkLxo+hqjGuvBlD2WD2q\n" +
                "RyMBtatMTCe4iyB61x/s+sSxe18YZLtZ8oZRAQIhANKE54m8XHicPfS/yPhVr28z\n" +
                "BKaIq5PGgkFBPEYRIC3hAiEAywEx4uH8o55ztn5R7wMaIUElyQxqzsxNuSth+nCJ\n" +
                "AssCIQCgpJ5ysnP17XQxwe+/4NLgjhPsaLpVJ9PZq8gsx4DAwQIgPVs/GLP1B/78\n" +
                "Okwzt2nYm/R01y9JmPdnBnB2TJt2zcECIQDLatpuog9RVPYTpJD8OZCsVIU6fcfp\n" +
                "Oi9Er6tG/gX35Q==";
        String publicKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKbwXyUjY2WHQTPFLRuz2S8vmGKu2ih7\n" +
                "mSqIyYc2Z2QV3oTjh8piNeD+16ImVoGfV2Huyj+B+Ic6YsqkttJJI2sCAwEAAQ==";


        privateKey =  privateKey.replace("\n","");
        publicKey =  publicKey.replace("\n","");
        System.out.println("privateKey = "+privateKey);
        System.out.println("publicKey = "+publicKey);
        String value = encrypt(publicKey,"{\"name\":\"dd\"}");
        System.out.println("加密后"+value);
        System.out.println("解密后"+decrypt(privateKey,value));


    }
}
